Auto Scaling環境でのBlue-Green Deploymentの切替がAWS ELBでできるようになりました。
超おはようございます。最近パンケーキを昼食にできるようになった城内です。 今回は、Auto Scalingのアップデートにより、AWSでのBlue-Green Deploymentの方式に新たな選択肢が増えたことを喜びたいと思います。
Auto Scalingのアップデート
先日のAuto Scalingのアップデートにより、Auto Scalingグループに対するELBの付け外しができるようになりました。
- Attach or Detach Load Balancers in Your Auto Scaling Group (What's New)
- Attach and Detach Elastic Load Balancers from Auto Scaling Groups (AWS Official Blog)
何が嬉しいのか?
従来、Auto Scalingに紐づくELBは変更することができず、AWS上でBlue-Green Deploymentの切替を行おうと思ったときには、DNSベース(Route53)の切替しかできませんでした。しかし、今回のAuto Scalingのアップデートにより、ELBでの切替が可能になりました。
切替方法
では、実際の切替方法ですが、いたって簡単です。今回はCLIベースでいきたいと思います。
環境構成
まず、構成は以下のような簡素な構成を前提に実施します。
CLIで確認すると、以下のような感じです。
# aws elb describe-load-balancers | jq '.LoadBalancerDescriptions[] | {LoadBalancerName, DNSName}' { "LoadBalancerName": "ELB-A", "DNSName": "ELB-A-87373750.ap-northeast-1.elb.amazonaws.com" } { "LoadBalancerName": "ELB-B", "DNSName": "ELB-B-55201029.ap-northeast-1.elb.amazonaws.com" } # aws autoscaling describe-auto-scaling-groups | jq '.AutoScalingGroups[] | {AutoScalingGroupName, LoadBalancerNames, Instances}' { "AutoScalingGroupName": "AutoScalingGroup-A", "LoadBalancerNames": [ "ELB-A" ], "Instances": [ { "InstanceId": "i-0d21ceff", "AvailabilityZone": "ap-northeast-1a", "HealthStatus": "Healthy", "LifecycleState": "InService", "LaunchConfigurationName": "webserver-20150618-01" } ] } { "AutoScalingGroupName": "AutoScalingGroup-B", "LoadBalancerNames": [ "ELB-B" ], "Instances": [ { "InstanceId": "i-8f21ce7d", "AvailabilityZone": "ap-northeast-1a", "HealthStatus": "Healthy", "LifecycleState": "InService", "LaunchConfigurationName": "webserver-20150618-01" } ] }
Green環境の本番組み込み
上記の構成から、本番アクセスがGreen環境(AutoScalingGroup-B)へも流れるようにします。Blue環境(AutoScalingGroup-A)に紐づいているELB-AをGreen環境にも取り付けます。
# aws autoscaling attach-load-balancers --auto-scaling-group-name 'AutoScalingGroup-B' --load-balancer-names 'ELB-A' # aws autoscaling describe-auto-scaling-groups | jq '.AutoScalingGroups[] | {AutoScalingGroupName, LoadBalancerNames, Instances}' { "AutoScalingGroupName": "AutoScalingGroup-A", "LoadBalancerNames": [ "ELB-A" ], "Instances": [ { "InstanceId": "i-0d21ceff", "AvailabilityZone": "ap-northeast-1a", "HealthStatus": "Healthy", "LifecycleState": "InService", "LaunchConfigurationName": "webserver-20150618-01" } ] } { "AutoScalingGroupName": "AutoScalingGroup-B", "LoadBalancerNames": [ "ELB-A", "ELB-B" ], "Instances": [ { "InstanceId": "i-8f21ce7d", "AvailabilityZone": "ap-northeast-1a", "HealthStatus": "Healthy", "LifecycleState": "InService", "LaunchConfigurationName": "webserver-20150618-01" } ] }
ここでは以下のような状態です。
Green環境への本番切替
上記では、Blue環境とGreen環境が両方本番環境として動作しています。ここから、Blue環境を切り離し、本番アクセスをGreen環境に完全に切り替えます。 オペレーションとしては、Blue環境からELB-Aを取り外し、Green環境からELB-Bを取り外します。
# aws autoscaling detach-load-balancers --auto-scaling-group-name 'AutoScalingGroup-A' --load-balancer-names 'ELB-A' # aws autoscaling detach-load-balancers --auto-scaling-group-name 'AutoScalingGroup-B' --load-balancer-names 'ELB-B' # aws autoscaling describe-auto-scaling-groups | jq '.AutoScalingGroups[] | {AutoScalingGroupName, LoadBalancerNames, Instances}' { "AutoScalingGroupName": "AutoScalingGroup-A", "LoadBalancerNames": [], "Instances": [ { "InstanceId": "i-0d21ceff", "AvailabilityZone": "ap-northeast-1a", "HealthStatus": "Healthy", "LifecycleState": "InService", "LaunchConfigurationName": "webserver-20150618-01" } ] } { "AutoScalingGroupName": "AutoScalingGroup-B", "LoadBalancerNames": [ "ELB-A" ], "Instances": [ { "InstanceId": "i-8f21ce7d", "AvailabilityZone": "ap-northeast-1a", "HealthStatus": "Healthy", "LifecycleState": "InService", "LaunchConfigurationName": "webserver-20150618-01" } ] }
最終的な状態は以下の通りです。
動作確認
上記作業の動作確認は、以下のようなPHPを作って確認してみました。
<?php require '/usr/local/aws/sdk-php/vendor/autoload.php'; $url = "http://169.254.169.254/latest/meta-data/instance-id/"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $instid = curl_exec($ch); curl_close($ch); use Aws\AutoScaling\AutoScalingClient; $client = AutoScalingClient::factory(array( 'region' => 'ap-northeast-1' )); $result = $client->describeAutoScalingInstances(array( 'InstanceIds' => array($instid) )); $asg = $result['AutoScalingInstances'][0]['AutoScalingGroupName']; if ($asg) { $msg = 'This instance (<strong>'.$instid.'</strong>) is attached to \'<strong>'.$asg.'</strong>\' AutoScalingGroup.'; } else { $msg = 'This instance is not attached to AutoScalingGroup.'; } echo <<<EOT <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Test Page</title> </head> <body> <p>$msg</p> </body> </html> EOT;
ブラウザでアクセスすると、どちらのAuto Scalingグループにアクセスしているのかが分かります。 切替がうまくいけば、以下のようにELB-AへのアクセスがBlue環境(AutoScalingGroup-A)からGreen環境(AutoScalingGroup-B)に切り替わります。
まとめ
うーん、いい感じに切り替えられますね!今回はあえて段階を踏んで切替を行いましたが、ほぼ一瞬で切替が可能です。DNSベースでの切替でもダウンタイムは発生しませんでしたが、DNSのキャッシュを考慮する必要がありました。今回の方法では、そんなことも気にせずにスパッと切り替えられて、とても気持ちいいですね。